package com.meida.module.arc.provider.handler;

import cn.afterturn.easypoi.util.WebFilenameUtils;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.configuration.OpenCommonProperties;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.utils.ApiAssert;
import com.meida.common.utils.JsonUtils;
import com.meida.module.arc.client.entity.*;
import com.meida.module.arc.client.enums.ArchiveEnumInteger;
import com.meida.module.arc.client.enums.CategoryTypeEnum;
import com.meida.module.arc.client.handler.ReportExportHandler;
import com.meida.module.arc.client.utils.ArcUtils;
import com.meida.module.arc.client.vo.ForEachIndex;
import com.meida.module.arc.provider.service.*;
import com.meida.module.arc.provider.util.FileConvertUtil;
import com.meida.module.file.provider.oss.FileUploadUtil;
import com.meida.module.system.client.entity.SysDept;
import com.meida.module.system.provider.service.SysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <b>功能名：ArcInfoReportHandler</b><br>
 * <b>说明：</b><br>
 * <b>著作权：</b> Copyright (C) 2021 HUIFANEDU  CORPORATION<br>
 * <b>修改履历：
 *
 * @author 2022-01-07 jiabing
 */
@Service("arcInfoReportHandler")
@Transactional(rollbackFor = Exception.class)
@DS("sharding")
@Slf4j
public class ArcInfoReportHandler implements ReportExportHandler {

    @Autowired
    private ArcReportService arcReportService;

    @Autowired
    private ArcInfoService arcInfoService;

    @Autowired
    private ArcFieldService arcFieldService;

    @Autowired
    private SysDeptService sysDeptService;

    @Autowired
    private ArcDictService arcDictService;

    @Autowired
    private ArcCategoryService arcCategoryService;
    @Autowired
    private OpenCommonProperties openCommonProperties;
    @Override
    public void export(Map params, HttpServletRequest request, HttpServletResponse response,String localTempPath,String exportName) {
        Object reportId = params.get("reportId");
        Object type = params.get("type");
        ApiAssert.isNotEmpty("报表id不能为空",reportId);
        Object arcInfoIds = params.get("arcInfoIds");
        ApiAssert.isNotEmpty("档案id不能为空",arcInfoIds);
        Object categoryId = params.get("categoryId");
        ApiAssert.isNotEmpty("门类id不能为空",categoryId);
        Object qzId = params.get("qzId");
        ApiAssert.isNotEmpty("全宗id不能为空",qzId);
        ArcReport report = this.arcReportService.getById(Long.parseLong(reportId.toString()));
        String[] arcInfoIdArr = arcInfoIds.toString().split(",");
        if(FlymeUtils.isEmpty(arcInfoIdArr)){
            ApiAssert.failure("档案id为空");
        }
        if(ArchiveEnumInteger.IS_TRUE.getCode().equals(report.getIsOne())&&arcInfoIdArr.length>1){
            ApiAssert.failure("报表配置为单条数据，但是传了多个档案");
        }
        ArcCategory category = this.arcCategoryService.getById(Long.parseLong(categoryId.toString()));
        CriteriaQuery<ArcInfo> criteriaQuery = new CriteriaQuery<ArcInfo>(ArcInfo.class);
        criteriaQuery.lambda().eq(ArcInfo::getCategoryId,Long.parseLong(categoryId.toString()))
                .in(ArcInfo::getArcInfoId, Arrays.stream(arcInfoIdArr).map(item->{
                    return Long.parseLong(item);
                }).collect(Collectors.toList()));
        List<ArcInfo> list = arcInfoService.list(criteriaQuery);

        ApiAssert.isNotEmpty("档案信息不能为空",list);


        List<Map<String,Object>> arcInfoListMap = list.stream().map(item->{
            Map<String,Object> mapObj =  BeanUtil.beanToMap(item);
            String expand = item.getExpand();
            mapObj.remove("expand");
            if(FlymeUtils.isNotEmpty(expand)){
                mapObj.putAll(JsonUtils.jsonToEntityMap(expand));
            }
            return mapObj;
        }).collect(Collectors.toList());


        CriteriaQuery<ArcField> arcFieldCriteriaQuery = new CriteriaQuery<ArcField>(ArcField.class);
        arcFieldCriteriaQuery.lambda().eq(ArcField::getCategoryId,Long.parseLong(categoryId.toString()));
        List<ArcField> fieldList = this.arcFieldService.list(arcFieldCriteriaQuery);
        Map<String, ArcField> fieldMap = fieldList.stream().collect(Collectors.toMap(ArcField::getFieldName, ArcField -> ArcField, (a, b) -> a));

        Map<String,String> unitMap = new HashMap<>();
        LambdaQueryWrapper<ArcDict>  lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.and(qw->qw.eq(ArcDict::getQzId,Long.parseLong(qzId.toString()))
                .or().eq(ArcDict::getIsSystem, ArchiveEnumInteger.IS_SYSTEM.getCode()));
        List<ArcDict> dictList = this.arcDictService.list(lambdaQueryWrapper);
        Map<String, String> dictMap = dictList.stream().collect(Collectors.toMap(ArcDict::getDictCode, ArcDict::getDictName, (a, b) -> a));
        //处理字典问题
        ForEachIndex index = new ForEachIndex();
        arcInfoListMap.forEach(item->{
            index.indexPlus();
           item.forEach((key,value)->{
               if(FlymeUtils.isNotEmpty(value)){
                   ArcField field = fieldMap.get(key);
                   if(field!=null){
                       //特殊字段处理
                       if("unitId".equals(key)&&FlymeUtils.isNotEmpty(value)){
                           if(FlymeUtils.isEmpty(unitMap)){
                               QueryWrapper<SysDept> query = new QueryWrapper();
                               query.lambda().eq(SysDept::getCompanyId,Long.parseLong(qzId.toString()));
                               List<SysDept> deptList = this.sysDeptService.list(query);
                               deptList.forEach(dept->{
                                   unitMap.put(dept.getDeptId().toString(),dept.getDeptName());
                               });
                           }
                           if(FlymeUtils.isNotEmpty(unitMap.get(value.toString()))){
                               item.put(key,unitMap.get(value.toString()));
                           }
                       }else{
                           //著录类型1文本框2数字框3日期框4下拉框5文本域6弹出框
                           if((4==field.getInType()||6==field.getInType())&&FlymeUtils.isNotEmpty(dictMap.get(value.toString()))){
                               item.put(key,dictMap.get(value.toString()));
                           }
                       }
                   }
               }
           });
           //扩展字段
           item.put("categoryName",category.getCnName());
           CategoryTypeEnum categoryTypeEnum = CategoryTypeEnum.getValue(category.getType());
           item.put("categoryType", categoryTypeEnum==null?"":categoryTypeEnum.getName());
           item.put("index",index.getIndex());
        });

        Map<String, Object> objInfo = arcInfoListMap.get(0);
        objInfo.put("list",arcInfoListMap);
        try {
            response.setHeader("content-disposition", WebFilenameUtils.disposition(exportName));
            ServletOutputStream out = response.getOutputStream();

            // 插件列表,可以去官网查看，有列循环，还有行循环，这里是行循环实例
            LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();

            //这里可以指定一个config类，用来指定一些规则，也可以改变模板中{{}}的这种格式
            Configure config = Configure.builder()
                    .bind("list", policy).build();
            String rootPath = ArcUtils.getRootTempPath();
            XWPFTemplate template = XWPFTemplate.compile(localTempPath, config);
            if (type != null && "doc".equals(type.toString())) {
                log.info("#############################直接预览");
                template.render(objInfo).writeAndClose(out);
            } else {
            //创建文件
            String fileBasePath = FileUploadUtil.datePath() + "/";
            String fileId= IdWorker.getIdStr();
            String fileName =fileId+ ".docx";
            FileUtil.mkdir(rootPath + fileBasePath);
            String path = rootPath + fileBasePath + fileName;
            template.render(objInfo).writeToFile(path);
            String imageBasePath=rootPath.substring(1) + fileBasePath +"image";
            //log.info("#############################开始WORD转图片"+imageBasePath);
           // FileConvertUtil.wordToImage(path.substring(1),imageBasePath );
            //File file = new File(path);
            //File targetDir = new File(file.getParentFile(), "pdf");
            //ConvertResult convertResult = OfficeUtils.convertPdf(file, targetDir, openCommonProperties.getOfficePath());
            //log.info("#############################转换图片成功"+imageBasePath);
            String pdfDir = rootPath.substring(1) + fileBasePath +"pdf";
            FileUtil.mkdir(pdfDir);
            String pdfPath=pdfDir+"/"+fileId+".pdf";

            //if (convertResult.isSuccess()) {
               // pdf = convertResult.getTargetFile();
            //}
            //FileConvertUtil.toPdf(imageBasePath+"/"+fileId,pdfPath);
            FileConvertUtil.wordToPdf(path.substring(1),pdfPath);
            FileInputStream inputStream = new FileInputStream(pdfPath);
            int i = inputStream.available(); // 得到文件大小
            byte[] data = new byte[i];
            inputStream.read(data); // 读数据
            inputStream.close();
            out.write(data); // 输出数据
            //template.render(objInfo).writeAndClose(out);
            out.flush();
            FileUtil.del(path.substring(1));
            FileUtil.del(pdfPath);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
